package edu.se.jai.gameservice.controller;


import edu.se.jai.gameservice.entity.GameRoom;
import edu.se.jai.gameservice.entity.Player;
import edu.se.jai.gameservice.service.GameService;
import edu.se.jai.openfeignapi.dto.*;
import edu.se.jai.openfeignapi.feign.GameServiceFeignApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 游戏服务REST控制器
 * 
 * 1. 实现 GameServiceFeignApi 接口
 * 2. 负责将Service内部实体转换为Feign API的DTO
 */
@Slf4j
@RestController
@RequestMapping("/api/game")
public class GameController implements GameServiceFeignApi {

    @Autowired
    private GameService gameService;

    // ==================== 玩家管理接口 ====================

    /**
     * 注册玩家会话
     */
    @Override
    public Result<String> registerPlayer( String sessionId,String playerName) {
        log.info("注册玩家: sessionId={}, playerName={}", sessionId, playerName);
        // 直接返回 Service 的结果
        return gameService.registerPlayerSession(sessionId, playerName);
    }

    // ==================== 房间管理接口 ====================

    /**
     * 创建房间
     */
    @Override
    public Result<GameRoomDto> createRoom(String sessionId) {
        log.info("创建房间: sessionId={}", sessionId);
        Result<GameRoom> result = gameService.createRoom(sessionId);
        
        if (result.isFailure()) {
            return Result.failure(result.getErrorMessage());
        }

        GameRoomDto roomDto = toGameRoomDto(result.getData());
        return Result.success(roomDto);
    }

    /**
     * 加入房间
     */
    @Override
    public Result<GameRoomDto> joinRoom(String sessionId,String roomId) {
        log.info("加入房间: sessionId={}, roomId={}", sessionId, roomId);
        Result<GameRoom> result = gameService.joinRoom(sessionId, roomId);
        
        if (result.isFailure()) {
            return Result.failure(result.getErrorMessage());
        }
        
        GameRoomDto roomDto = toGameRoomDto(result.getData());
        return Result.success(roomDto);
    }

    /**
     * 离开房间
     */
    @Override
    public Result<GameRoomDto> leaveRoom(String sessionId,String roomId) {
        log.info("离开房间: sessionId={}, roomId={}", sessionId, roomId);
        Result<GameRoom> result = gameService.leaveRoom(sessionId, roomId);
        
        if (result.isFailure()) {
            return Result.failure(result.getErrorMessage());
        }
        
        GameRoomDto roomDto =toGameRoomDto(result.getData());
        return Result.success(roomDto);
    }

    /**
     * 解散房间
     */
    @Override
    public Result<GameRoomDto> dissolveRoom( String sessionId, String roomId) {
        log.info("解散房间: sessionId={}, roomId={}", sessionId, roomId);
        Result<GameRoom> result = gameService.dissolveRoom(sessionId, roomId);
        
        if (result.isFailure()) {
            return Result.failure(result.getErrorMessage());
        }
        
        GameRoomDto roomDto = toGameRoomDto(result.getData());
        return Result.success(roomDto);
    }

    /**
     * 获取所有房间列表
     */
    @Override
    public Result<List<GameRoomDto>> getAllRooms() {
        log.info("获取所有房间列表");
        List<GameRoom> rooms = gameService.getAllRooms();

        List<GameRoomDto> roomDtos = rooms.stream()
                .map(this::toGameRoomDto)
                .collect(Collectors.toList());
        
        return Result.success(roomDtos);
    }

    /**
     * 根据会话ID获取所在房间
     */
    @Override
    public Result<GameRoomDto> getRoomBySessionId(String sessionId) {
        log.info("根据会话ID获取房间: sessionId={}", sessionId);
        GameRoom room = gameService.getRoomBySessionId(sessionId);
        
        if (room == null) {
            return Result.failure("房间不存在");
        }
        
        GameRoomDto roomDto = toGameRoomDto(room);
        return Result.success(roomDto);
    }

    /**
     * 根据房间ID获取房间
     */
    @Override
    public Result<GameRoomDto> getRoomById(@PathVariable("roomId") String roomId) {
        log.info("根据房间ID获取房间: roomId={}", roomId);
        GameRoom room = gameService.getRoomById(roomId);
        
        if (room == null) {
            return Result.failure("房间不存在");
        }
        
        GameRoomDto roomDto = toGameRoomDto(room);
        return Result.success(roomDto);
    }

    // ==================== 游戏逻辑接口 ====================

    /**
     * 开始游戏
     * TODO: 练习二.1 - 实现 startGame 方法
     * 要求：
     * 1. 调用 gameService.startGame() 方法
     * 2. 处理返回结果，失败时返回错误信息
     * 3. 成功时将 GameRoom 实体转换为 GameRoomDto
     */
    @Override
    public Result<GameRoomDto> startGame( String sessionId,String roomId) {
        // TODO: 实现开始游戏逻辑

        // 临时返回，避免编译错误
        return Result.failure("请实现 startGame 方法");
    }

    /**
     * 停止游戏
     * TODO: 练习二.2 - 实现 stopGame 方法
     * 要求：
     * 1. 调用 gameService.stopGame() 方法
     * 2. 处理返回结果，失败时返回错误信息
     * 3. 成功时将 GameRoom 实体转换为 GameRoomDto
     */
    @Override
    public Result<GameRoomDto> stopGame( String sessionId,String roomId) {
        // TODO: 实现停止游戏逻辑

        // 临时返回，避免编译错误
        return Result.failure("请实现 stopGame 方法");
    }

    /**
     * 猜测数字
     * TODO: 练习二 - 实现 makeGuess 方法
     * 要求：
     * 1. 调用 gameService.makeGuess() 方法
     * 2. 直接返回 GuessResultDto，无需转换
     * 3. 注意：GameService.makeGuess() 直接返回 GuessResultDto，不是内部实体
     */



    /**
     * 将内部GameRoom实体转换为GameRoomDto（不包含targetNumber）
     */
    public  GameRoomDto toGameRoomDto(GameRoom room) {
        if (room == null) {
            return null;
        }
        GameRoomDto dto = new GameRoomDto();
        dto.setRoomId(room.getRoomId());
        dto.setCreatorName(room.getCreatorName());
        // targetNumber 故意不设置，保持敏感信息不暴露
        dto.setStatus(room.getStatus());

        // 转换players Map
        if (room.getPlayers() != null) {
            List<String> nameList= room.getPlayers().values()
                    .stream()
                    .map(Player::getName)
                    .collect(Collectors.toList());
            dto.setPlayers(nameList);
        } else {
            dto.setPlayers(new ArrayList<>());
        }

        return dto;
    }
}
